
package codeGenerate.mybatis.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import codeGenerate.common.utils.SystemUtils;
import codeGenerate.custom.tempalte.TemPathCustom;
import codeGenerate.mybatis.constants.DBType;
import codeGenerate.mybatis.generater.AbstractGenerater;
import codeGenerate.mybatis.generater.imp.ClickhouseGenerater;
import codeGenerate.mybatis.generater.imp.CommonGenerater;
import codeGenerate.mybatis.generater.imp.MysqlGenerater;
import codeGenerate.mybatis.generater.imp.OracleGenerater;
import codeGenerate.mybatis.generater.imp.SqlServer2005Generater;
import codeGenerate.mybatis.vo.ConfigVo;

public class GenUtils {

	/**
	 * @description: 配置文件路径
	 * @creator: dw-fu1
	 * @createDate: 2018年2月26日 
	 * @modifier:
	 * @modifiedDate:
	 * @param configPath 配置路径
	 * @throws Exception
	 */
	public static void genCode(String configPath) throws Exception {
		File file = new File(configPath);
		if (!file.exists()) {
			System.out.println("文件不存在：" + configPath);
		}
		FileInputStream is = new FileInputStream(file);
		genCode(is);
	}

	/**
	 * @description: 流
	 * @creator: dw-fu1
	 * @createDate: 2018年2月26日 
	 * @modifier:
	 * @modifiedDate:
	 * @param is
	 * @throws Exception
	 */
	public static void genCode(InputStream is) throws Exception {
		List<ConfigVo> configList = readConfig(is);
		for (ConfigVo cf : configList) {
			AbstractGenerater generater = getByDbType(cf.getDbType());
			generater.setConfigVo(cf);
			generater.generateCode();
		}
	}

	@SuppressWarnings("unchecked")
	public static List<ConfigVo> readConfig(InputStream is) throws IOException, DocumentException {
		try {

			List<ConfigVo> configVoList = new ArrayList<>();

			//创建解析器
			SAXReader reader = new SAXReader();
			//得到document
			Document document = reader.read(is);
			Element root = document.getRootElement();
			String driverName = root.elementText("driverName");
			String url = root.elementText("url");
			String dbName = root.elementText("dbName");
			String userName = root.elementText("userName");
			String password = root.elementText("password");
			String createUser = root.elementText("createUser");
			String copyright = root.elementText("copyright");
			String template = root.elementText("template");
			String genPath = root.elementText("genPath");
			String templateDirectory = root.elementText("templateDirectory");
			if (StringUtils.isBlank(template)) {
				template = TemPathCustom.class.getName();
			}
			if (StringUtils.isBlank(templateDirectory)) {
				templateDirectory = SystemUtils.defalutTemplateDirectory();
			}

			Element beansEle = root.element("beans");

			List<Element> beanEles = beansEle.elements("bean");
			for (Element beanEle : beanEles) {
				ConfigVo cv = new ConfigVo();
				cv.setDriverName(driverName);
				cv.setUrl(url);
				cv.setUsername(userName);
				cv.setPassword(password);
				cv.setDbName(dbName);
				cv.setDbType(DBType.getByDriverName(driverName));
				cv.setCreateUser(createUser);
				cv.setCreateTime(new Date());
				cv.setCopyright(copyright);
				cv.setTemplate(template);
				cv.setTemplateDirectory(templateDirectory);
				cv.setGenPath(genPath);
				cv.setBeanDescription(beanEle.attributeValue("desc"));
				cv.setTblName(beanEle.attributeValue("tableName"));
				cv.setBeanName(
						StringUtils.capitalize(StringUtils.defaultIfBlank(beanEle.attributeValue("beanName"), SystemUtils.getBeanNameByPath(beanEle.attributeValue("path")))));
				cv.setPack(beanEle.attributeValue("path"));

				Map<String, String> beanAttributeMap = new HashMap<>();
				List<Attribute> attributes = beanEle.attributes();
				for (Attribute attr : attributes) {
					beanAttributeMap.put(attr.getName(), attr.getValue());
				}
				cv.setBeanAttributeMap(beanAttributeMap);
				configVoList.add(cv);
			}

			//验证
			for (ConfigVo configVo : configVoList) {
				if (StringUtils.isBlank(configVo.getDriverName())) {
					throw new RuntimeException("驱动名不能为空");
				}
				if (StringUtils.isBlank(configVo.getUrl())) {
					throw new RuntimeException("连接地址不能为空");
				}
				if (StringUtils.isBlank(configVo.getUsername())) {
					throw new RuntimeException("用户名称不能为空");
				}
				if (StringUtils.isBlank(configVo.getPassword())) {
					throw new RuntimeException("用户密码不能为空");
				}
				if (StringUtils.isBlank(configVo.getCreateUser())) {
					throw new RuntimeException("创建用户不能为空");
				}
				if (StringUtils.isBlank(configVo.getTemplate())) {
					throw new RuntimeException("生成模版不能为空");
				}
				if (StringUtils.isBlank(configVo.getGenPath())) {
					throw new RuntimeException("文件夹存放路径不能为空");
				}
				if (StringUtils.isBlank(configVo.getTblName())) {
					throw new RuntimeException("表名不能为空");
				}
				if (StringUtils.isBlank(configVo.getPack())) {
					throw new RuntimeException("包路径不能为空");
				}
				if (StringUtils.isBlank(configVo.getBeanDescription())) {
					throw new RuntimeException("bean描述不能为空");
				}
			}
			return configVoList;
		} finally {
			is.close();
		}

	}

	/**
	 * @description: 根据数据库类型获取相应的代码生成器
	 * @creator: dw-fu1
	 * @createDate: 2018年3月23日 
	 * @modifier:
	 * @modifiedDate:
	 * @param dbType
	 * @return
	 */
	private static AbstractGenerater getByDbType(String dbType) {
		if (DBType.MYSQL.equals(dbType)) {
			return new MysqlGenerater();
		}
		if (DBType.ORACLE.equals(dbType)) {
			return new OracleGenerater();
		}
		if (DBType.SQLSERVER2005.equals(dbType)) {
			return new SqlServer2005Generater();
		}
		if (DBType.SQLSERVER.equals(dbType)) {
			return new SqlServer2005Generater();
		}
		if (DBType.CLICKHOUSE.equals(dbType)) {
			return new ClickhouseGenerater();
		}
		return new CommonGenerater();
	}
}
